package com.xpu.stock.service.impl;

import com.alibaba.excel.EasyExcel;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.gson.Gson;
import com.xpu.stock.common.domain.InnerMarketDomain;
import com.xpu.stock.common.domain.Stock4EvrDayDomain;
import com.xpu.stock.common.domain.Stock4MinuteDomain;
import com.xpu.stock.common.domain.StockUpdownDomain;
import com.xpu.stock.config.vo.StockInfoConfig;
import com.xpu.stock.mapper.StockBusinessMapper;
import com.xpu.stock.mapper.StockMarketIndexInfoMapper;
import com.xpu.stock.mapper.StockRtInfoMapper;
import com.xpu.stock.pojo.StockBusiness;
import com.xpu.stock.service.StockService;
import com.xpu.stock.utils.DateTimeUtil;
import com.xpu.stock.vo.resp.PageResult;
import com.xpu.stock.vo.resp.ResponseCode;
import com.xpu.stock.vo.resp.Result;
import org.checkerframework.checker.units.qual.A;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;

@Service
public class StockServiceImpl implements StockService {
    @Autowired
    private StockBusinessMapper stockBusinessMapper;
    @Autowired
    private StockMarketIndexInfoMapper stockMarketIndexInfoMapper;
    @Autowired
    private StockInfoConfig stockInfoConfig;
    @Autowired
    private StockRtInfoMapper stockRtInfoMapper;

    @Override
    public List<StockBusiness> findAll() {
        return stockBusinessMapper.findAll();
    }

    @Override
    public Result<List<InnerMarketDomain>> getNewAMarketInfo() {
        //1.获取国内A股大盘的id集合
        List<String> inners = stockInfoConfig.getInner();
        //2.获取最近股票交易日期
        DateTime lastDateTime = DateTimeUtil.getLastDate4Stock(DateTime.now());
        //3.转Java中的date
        Date lastDate = lastDateTime.toDate();
        //TODO mock测试数据，后期数据通过第三方接口动态获取实时数据，可删除
        lastDate = DateTime.parse("2022-01-03 11:15:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        //4.将获取的Java Date传入接口
        List<InnerMarketDomain> list = stockMarketIndexInfoMapper.getMarketInfo(inners, lastDate);
        return Result.ok(list);
    }

    @Override
    public Result<List<StockUpdownDomain>> getStockRtInfoLimit() {
        //1.获取最近最新的股票有效交易时间点（精确到分钟）
        Date lastdate = DateTimeUtil.getLastDate4Stock(DateTime.now()).toDate();
        //TODO mock数据
        lastdate = DateTime.parse("2021-12-30 09:42:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        //调用mapper查询
        List<StockUpdownDomain> list = stockRtInfoMapper.getStockRtInfoLimit(lastdate);
        //判断集合装填
        if (CollectionUtils.isEmpty(list)) {
            return Result.error(ResponseCode.NO_RESPONSE_DATA.getMessage());
        }
        return Result.ok(list);
    }

    @Override
    public Result<PageResult<StockUpdownDomain>> getStockInfo4Page(Integer page, Integer pageSize) {
        //设置分页参数
        PageHelper.startPage(page, pageSize);
        //2.查询
        List<StockUpdownDomain> pages = stockRtInfoMapper.getStockInfo4All();
        if (CollectionUtils.isEmpty(pages)) {
            return Result.error(ResponseCode.NO_RESPONSE_DATA.getMessage());
        }
        //3.组装pageInfo对象，pageInfo对象封装了一切分页信息，我们只需要它的部分信息即可
        PageInfo<StockUpdownDomain> pageInfo = new PageInfo<>(pages);
        //4.转换成自定义的分页对象
        PageResult<StockUpdownDomain> pageResult = new PageResult<>(pageInfo);
        return Result.ok(pageResult);
    }

    @Override
    public Result<Map> getStockUpDownCount() {
        //1.借助工具类获取最近交易日的开盘时间和收盘时间
        //获取有效时间点
        DateTime avavbleTimePoint = DateTimeUtil.getLastDate4Stock(DateTime.now());
        //根据有效时间点获取对应日期的开盘和收盘时间
        Date openTime = DateTimeUtil.getOpenDate(avavbleTimePoint).toDate();
        Date closeTime = DateTimeUtil.getCloseDate(avavbleTimePoint).toDate();
        //TODO mock 数据
        openTime = DateTime.parse("2021-12-19 09:30:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        closeTime = DateTime.parse("2021-12-19 15:00:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        //2.查询涨停的统计数据
        List<Map> upList=stockRtInfoMapper.getStockUpDownCount(openTime,closeTime,1);
        //3.查询跌停的统计数据
        List<Map> downList=stockRtInfoMapper.getStockUpDownCount(openTime,closeTime,0);
        //4.组装map，将涨停和跌停的数据组装到map中
        HashMap<String,List> map=new HashMap<>();
        map.put("upList",upList);
        map.put("downList",downList);
        //5.返回结果
        return Result.ok(map);
    }

    /**
     * 通过response对象，以流的形式给前端响应文件对象
     * @param response http的响应对象，可获取流对象，写出对象
     * @param page 当前页
     * @param pageSize 每页大小
     */
    @Override
    public void stockExport(HttpServletResponse response, Integer page, Integer pageSize) throws IOException {
        //1.设置响应数据类型：excel
        response.setContentType("application/vnd.ms-excel");
        //2.设置响应数据的编码格式
        response.setCharacterEncoding("utf-8");
        //3.设置默认文件名称
        //这里URLEncoder.encode可以防止中文乱码，和easyexcel没有关系
        String fileName = URLEncoder.encode("stock", "UTF-8");
        response.setHeader("content-disposition", "attachment;filename=" + fileName + ".xls");
        //读取数据导出集合
        //设置分页参数
        PageHelper.startPage(page,pageSize);
        //查询
        List<StockUpdownDomain> pages = stockRtInfoMapper.getStockInfo4All();
        if (CollectionUtils.isEmpty(pages)) {
             Result<String> error=Result.error(ResponseCode.NO_RESPONSE_DATA.getMessage());
             //将错误信息转化成json字符串响应前端
            String jsonData=new Gson().toJson(error);
            //响应前端错误数据
            response.getWriter().write(jsonData);
            //终止当前程序
            return;
        }
        EasyExcel.write(response.getOutputStream(),StockUpdownDomain.class)
                .sheet("stockInfo").doWrite(pages);
    }

    @Override
    public Result<Map> getStockTradeVol4Comparsion() {
        //1.获取T日和T-1日的开始时间和结束时间
        //1.1获取最近有效交易时间点
        DateTime lastDateTime = DateTimeUtil.getLastDate4Stock(DateTime.now());
        DateTime openDateTime = DateTimeUtil.getOpenDate(lastDateTime);
        //转换成Java中的date，这样jdbc才能默认识别
        Date startTime4T = openDateTime.toDate();
        Date endTime4T=lastDateTime.toDate();
        //TODO mock数据
        startTime4T=DateTime.parse("2022-01-03 09:30:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        endTime4T=DateTime.parse("2022-01-03 14:40:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        //1.2获取T-1日的区间范围
        //获取lastDateTime的上一个股票交易日
        DateTime preLastDateTime = DateTimeUtil.getPreviousTradingDay(lastDateTime);//这里也可以直接减一天然后再获取最近有效交易日期
        DateTime preOpenDateTime = DateTimeUtil.getOpenDate(preLastDateTime);
        //转换T-1时间组为Java date对象
        Date startTime4PreT=preOpenDateTime.toDate();
        Date endTime4PreT=preLastDateTime.toDate();
        //TODO mock数据
        startTime4PreT=DateTime.parse("2022-01-02 09:30:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        endTime4PreT=DateTime.parse("2022-01-02 14:40:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        //2.获取上证和深证的配置大盘id
        //2.1获取大盘id集合
        List<String> marketIds = stockInfoConfig.getInner();
        //3.分别查询T日和T-1日的交易数据，得到两个集合
        //3.1查询T日大盘交易统计数据
        List<Map> date4T=stockMarketIndexInfoMapper.getStockTradeVol(marketIds,startTime4T,endTime4T);
        if (CollectionUtils.isEmpty(date4T)) {
            date4T=new ArrayList<>();
        }
        //3.2查询T-1日大盘交易统计数据
        List<Map> date4PreT=stockMarketIndexInfoMapper.getStockTradeVol(marketIds,startTime4PreT,endTime4PreT);
        if (CollectionUtils.isEmpty(date4PreT)) {
            date4PreT=new ArrayList<>();
        }
        //4.组装响应数据
        HashMap<String, List> info = new HashMap<>();
        info.put("volList",date4T);
        info.put("yesVolList",date4PreT);
        //5.返回数据
        return Result.ok(info);
    }

    @Override
    public Result<Map> getStockUpDownRegion() {
        DateTime dateTime4Stock = DateTimeUtil.getLastDate4Stock(DateTime.now());
        //获取股票最新交易时间
        Date lastDate = dateTime4Stock.toDate();
        //TODO mock
        lastDate=DateTime.parse("2021-12-30 09:42:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        //插入mapper接口获取统计数据
        List<Map> infos=stockRtInfoMapper.getStockUpDownRegion(lastDate);
        //组装数据并响应
        HashMap<String, Object> date = new HashMap<>();
        //获取日期格式
        String stringDateTime = dateTime4Stock.toString(DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"));
        date.put("time",stringDateTime);
        date.put("infos",infos);
        return Result.ok(date);
    }

    @Override
    public Result<List<Stock4MinuteDomain>> stockScreenTimeSharing(String stockCode) {
        //1.获取最近最新的交易时间点和对应的开盘日期
        DateTime lastDate4Stock = DateTimeUtil.getLastDate4Stock(DateTime.now());
        Date endTime = lastDate4Stock.toDate();
        //TODO mock
        endTime=DateTime.parse("2021-12-30 14:47:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        //1.2获取最近有效时间点的开盘时间
        DateTime openDateTime = DateTimeUtil.getOpenDate(lastDate4Stock);
        Date startTime = openDateTime.toDate();
        //TODO mock
        startTime=DateTime.parse("2021-12-30 09:30:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        //根据股票code和日期范围查询
        List<Stock4MinuteDomain> list=stockRtInfoMapper.getStockInfoByCodeAndDate(stockCode,startTime,endTime);
        //判断非空处理
        if (CollectionUtils.isEmpty(list)) {
            list=new ArrayList<>();
        }
        //3.返回响应数据
        return Result.ok(list);
    }

    @Override
    public Result<List<Stock4EvrDayDomain>> stockScreenDkLine(String code) {
       //获取查询的日期范围
        //获取截止时间
        DateTime endDateTime = DateTimeUtil.getLastDate4Stock(DateTime.now());
        Date endTime = endDateTime.toDate();
        //TODO mock date
        endTime=DateTime.parse("2022-01-07 15:00:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        //获取开始时间
        DateTime startDateTime = endDateTime.minusDays(10);
        Date startTime = startDateTime.toDate();
        //TODO mock date
        startTime=DateTime.parse("2022-01-01 09:30:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        //调用mapper接口获取查询的集合信息
        List<Stock4EvrDayDomain> data=stockRtInfoMapper.getStockInfo4EvrDay(code,startTime,endTime);
        if (CollectionUtils.isEmpty(data)) {
            data=new ArrayList<>();
        }
       //组装数据响应
        return Result.ok(data);
    }

    /*@Override
    public Result<Map> upDownCount() {
        //1.获取股票最近的有效交易日期,精确到秒
        DateTime curDateTime = DateTimeUtil.getLastDate4Stock(DateTime.now());
        //当前最近有效期
        Date curTime = curDateTime.toDate();
        //开盘日期
        Date openTime = DateTimeUtil.getOpenDate(curDateTime).toDate();
        //TODO mock_data 后续数据实时获取时，注释掉
        String curTimeStr="20220106142500";
        //对应开盘日期 mock_data
        String openTimeStr="20220106092500";
        curTime = DateTime.parse(curTimeStr, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
        openTime = DateTime.parse(openTimeStr, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
        //2.统计涨停的数据 约定：1代表涨停 0：跌停
        List<Map> upCount= stockRtInfoMapper.upDownCount(curTime,openTime,1);
        //3.统计跌停的数据
        List<Map> downCount= stockRtInfoMapper.upDownCount(curTime,openTime,0);
        //4.组装数据到map
        HashMap<String, List<Map>> info = new HashMap<>();
        info.put("upList",upCount);
        info.put("downList",downCount);
        //5.响应
        return Result.ok(info);

    }*/
}
